package com.magina.mq.rabbit.exchange.direct;

import com.magina.mq.constant.GloablFlag;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;

/**
 * 文件名称：ErrorReceiver</br>
 * 初始作者： Magina.Hu</br>
 * 创建日期： 2019/5/10</br>
 * 功能说明： direct类型的Exchange路由规则也很简单，它会把消息路由到那些binding key与routing key完全匹配的Queue中。 <br/>
 * =================================================<br/>
 * 修改记录：<br/>
 * 修改作者 日期 修改内容<br/>
 * ================================================<br/>
 * Copyright (c) 2019-2020 .All rights reserved.<br/>
 */
@Component
@Slf4j
@RabbitListener(
        bindings=@QueueBinding(
                value = @Queue(value = "${rab.cass.config.quene.error}",autoDelete="true"),
                exchange =@Exchange(value = "${rab.cass.config.exchange}",type =ExchangeTypes.DIRECT),
                key = "${rab.cass.config.quene.error.routing.key}"
        )
)
public class ErrorReceiver {

    @Value("${rab.cass.config.quene.error}")
    private String errorQueueName;



    /**
     * 方法描述:
     *  channel.basicAck()参数
     *  deliveryTag:该消息的index
     *  multiple：是否批量.true:将一次性拒绝所有小于deliveryTag的消息。
     *  requeue：被拒绝的是否重新入队列</br>
     * 初始作者: Magina.Hu<br/>
     * 创建日期: 2019/5/13 <br/>
     * 开始版本: 1.0.0<br/>
     * =================================================<br/>
     * 修改记录：<br/>
     * 修改作者 日期 修改内容<br/>
     * ================================================<br/>
     * @param  入参对象
     * @return  返回数据
     * @throws Exception 异常
     */
    @RabbitHandler
    public void process(String msg, Channel channel, @Header(name = "amqp_deliveryTag") long deliveryTag,
                        @Header("amqp_redelivered") boolean redelivered, @Headers Map<String, String> head) throws IOException {
        try {
            GloablFlag.flagCount.incrementAndGet();
            if (GloablFlag.flagCount.get() % 2 == 1) {
                String resultStr = "RabbitMq:" + errorQueueName + " consumer 收到一条信息: " + msg;
                System.out.println(resultStr);
                channel.basicAck(deliveryTag, false);
            } else {
                throw new RuntimeException("测试消费者抛出异常!");
            }
        } catch (Exception e) {
            String resultStr = "RabbitMq:" + errorQueueName + " consumer 收到一条信息: " + msg;
            System.out.println(resultStr + e.getMessage());
            channel.basicReject(deliveryTag, false);
            channel.basicNack(deliveryTag, false,true);//将消息继续放回队列等待消费
        }
    }

//        @RabbitHandler
//        public void process(String msg, Channel channel, @Header(name = "amqp_deliveryTag") long deliveryTag,
//        @Header("amqp_redelivered") boolean redelivered, @Headers Map<String, String> head) throws IOException {
//            try {
//                log.info("ConsumerWithConfirm receive message:{},header:{}", msg, head);
//                channel.basicAck(deliveryTag, false);
//            } catch (Exception e) {
//                log.error("consume confirm error!", e);
//                //这一步千万不要忘记，不会会导致消息未确认，消息到达连接的qos之后便不能再接收新消息
//                //一般重试肯定的有次数，这里简单的根据是否已经重发过来来决定重发。第二个参数表示是否重新分发
////                channel.basicReject(deliveryTag, !redelivered);
//                //这个方法我知道的是比上面多一个批量确认的参数
//                 channel.basicNack(deliveryTag, false,!redelivered);
//            }
//        }

}
